import pygame
import pygame_gui
from typing import Optional, List
import sys
import os

# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from utils import get_chinese_font
from game.character import Character
from game.card import Card
from game.game_engine import GameEngine, ROLE_LORD, ROLE_LOYAL, ROLE_REBEL, ROLE_TRAITOR

class GameWindow:
    """游戏窗口类，负责游戏过程中的界面显示和交互"""
    def __init__(self, window, manager):
        # 从外部接收窗口和管理器
        self.window = window
        self.manager = manager
        self.width, self.height = window.get_width(), window.get_height()
        
        # 背景颜色
        self.background_color = (205, 133, 63)
        
        # 时钟
        self.clock = pygame.time.Clock()
        
        # 游戏状态
        self.state = "setup"  # setup, playing, game_over
        
        # 设置玩家数量选择器
        self.player_count = 5  # 默认5人局
        self.player_count_slider = None
        self.player_count_label = None
        self.start_game_button = None
        self.back_button = None
        
        # 获取中文字体（不同大小）
        self.font = get_chinese_font(24)  # 普通字体
        self.small_font = get_chinese_font(18)  # 小字体
        self.large_font = get_chinese_font(32)  # 大字体
        
        # 初始化界面元素
        self._setup_ui_elements()
        
        # 记录选中的卡牌
        self.selected_card = None
    
    def _setup_ui_elements(self):
        """设置UI元素"""
        # 玩家数量选择器
        self.player_count_label = pygame_gui.elements.UILabel(
            relative_rect=pygame.Rect((self.width//2 - 150, 200), (300, 30)),
            text=f'玩家数量: {self.player_count}',
            manager=self.manager
        )
        
        self.player_count_slider = pygame_gui.elements.UIHorizontalSlider(
            relative_rect=pygame.Rect((self.width//2 - 200, 250), (400, 30)),
            start_value=5,
            value_range=(4, 8),
            manager=self.manager
        )
        
        self.start_game_button = pygame_gui.elements.UIButton(
            relative_rect=pygame.Rect((self.width//2 - 100, 350), (200, 50)),
            text='开始游戏',
            manager=self.manager
        )
        
        # 创建一个隐藏的返回按钮
        self.back_button = pygame_gui.elements.UIButton(
            relative_rect=pygame.Rect((self.width//2 - 100, self.height//2 + 50), (200, 50)),
            text='返回主菜单',
            manager=self.manager
        )
        self.back_button.hide()
    
    def handle_setup_event(self, event: pygame.event.Event) -> str:
        """处理游戏设置事件"""
        self.manager.process_events(event)
        
        if event.type == pygame.USEREVENT:
            if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                if event.ui_element == self.start_game_button:
                    # 隐藏设置界面元素
                    self.player_count_slider.hide()
                    self.player_count_label.hide()
                    self.start_game_button.hide()
                    # 更新游戏状态
                    self.state = "playing"
                    return "start_playing"
            
            elif event.user_type == pygame_gui.UI_HORIZONTAL_SLIDER_MOVED:
                if event.ui_element == self.player_count_slider:
                    self.player_count = int(event.value)
                    self.player_count_label.set_text(f'玩家数量: {self.player_count}')
        
        return None
    
    def handle_game_event(self, event: pygame.event.Event, game_engine: GameEngine) -> str:
        """处理游戏进行中的事件"""
        self.manager.process_events(event)
        
        # 获取当前玩家
        current_player = game_engine.get_current_player()
        
        # 处理鼠标点击
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            # 获取鼠标位置
            mouse_pos = pygame.mouse.get_pos()
            # 处理卡牌点击
            card = self._get_clicked_card(mouse_pos, game_engine)
            if card:
                # 处理卡牌选择
                self.selected_card = card
                # 这里可以添加选中卡牌后的逻辑
                print(f"选中卡牌: {card.name}")
                # 卡牌使用逻辑
                self._handle_card_use(card, game_engine, current_player)
        
        # 处理键盘事件，结束出牌阶段
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and current_player and current_player.is_human:
                # 空格键结束出牌阶段
                print(f"{current_player.name} 结束出牌阶段")
                game_engine.current_phase = "弃牌阶段"
                return "next_phase"
        
        # 对于AI玩家，自动处理回合进度
        if current_player and not current_player.is_human and game_engine.current_phase == "出牌阶段":
            # 检查AI是否已经完成了出牌阶段的处理
            # 如果AI的出牌阶段处理已完成，自动进入弃牌阶段
            # 这里假设有一个简单的计数器，当AI处理完后自动推进
            if not hasattr(self, 'ai_phase_timer'):
                self.ai_phase_timer = 0
            else:
                self.ai_phase_timer += 1
                
            # 每隔一定帧数自动推进AI回合
            if self.ai_phase_timer > 60:  # 等待约1秒
                game_engine.current_phase = "弃牌阶段"
                self.ai_phase_timer = 0
        
        return None
    
    def handle_game_over_event(self, event: pygame.event.Event) -> str:
        """处理游戏结束事件"""
        self.manager.process_events(event)
        
        if event.type == pygame.USEREVENT:
            if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                if event.ui_element == self.back_button:
                    # 隐藏返回按钮
                    self.back_button.hide()
                    return "back_to_menu"
        
        return None
    
    def render(self, game_engine: Optional[GameEngine]):
        """渲染游戏界面"""
        # 填充背景
        self.window.fill(self.background_color)
        
        if self.state == "setup":
            # 渲染设置界面
            self._render_setup_screen()
        elif self.state == "playing" and game_engine:
            # 渲染游戏界面
            self._render_game_screen(game_engine)
        elif self.state == "game_over" and game_engine:
            # 渲染游戏结束界面
            self._render_game_over_screen(game_engine)
    
    def _render_setup_screen(self):
        """渲染设置界面"""
        title = self.large_font.render("游戏设置", True, (255, 255, 255))
        self.window.blit(title, (self.width//2 - title.get_width()//2, 100))
        
        # 绘制说明文本
        desc = self.small_font.render("请选择游戏人数", True, (255, 255, 255))
        self.window.blit(desc, (self.width//2 - desc.get_width()//2, 150))
    
    def _handle_card_use(self, card, game_engine, current_player):
        """处理卡牌使用"""
        if not current_player or not current_player.is_human:
            return
            
        # 基础牌使用逻辑
        if card.card_type == "basic":
            if card.name == "杀":
                # 寻找合适的攻击目标
                for target in game_engine.get_characters():
                    if target != current_player and not target.dead and self._is_in_attack_range(current_player, target):
                        if self._use_attack_card(game_engine, current_player, target, card):
                            # 使用成功，清除选中状态
                            self.selected_card = None
                        break
            elif card.name == "桃" and current_player.health < current_player.max_health:
                # 使用桃恢复体力
                self._use_heal_card(game_engine, current_player, card)
                self.selected_card = None
            elif card.name == "闪":
                print("闪需要在被攻击时使用")
            elif card.name == "酒":
                # 使用酒
                self._use_wine_card(game_engine, current_player, card)
                self.selected_card = None
        # 装备牌使用逻辑
        elif card.card_type == "equipment":
            # 装备卡牌
            self._equip_card(game_engine, current_player, card)
            self.selected_card = None
        # 锦囊牌使用逻辑
        elif card.card_type == "trick":
            # 简化处理，自动使用锦囊
            self._use_trick_card(game_engine, current_player, card)
            self.selected_card = None
    
    def _use_attack_card(self, game_engine, player, target, card):
        """使用杀攻击目标"""
        # 检查目标是否在攻击范围内
        if not self._is_in_attack_range(player, target):
            print(f"目标太远，无法攻击 {target.name}")
            return False
        
        # 使用杀牌
        if hasattr(card, 'use'):
            if card.use(game_engine, player, target):
                # 使用成功
                print(f"{player.name} 使用杀攻击了 {target.name}！")
                # 确保从手牌移除
                if card in player.hand:
                    player.hand.remove(card)
                    # 添加到弃牌堆
                    if hasattr(game_engine, 'discard_pile'):
                        game_engine.discard_pile.append(card)
                return True
        else:
            # 如果没有use方法，进行简化处理
            print(f"{player.name} 使用杀攻击了 {target.name}！")
            # 造成伤害
            target.take_damage(1)
            # 从手牌移除
            if card in player.hand:
                player.hand.remove(card)
                # 添加到弃牌堆
                if hasattr(game_engine, 'discard_pile'):
                    game_engine.discard_pile.append(card)
            return True
        
        return False
    
    def _use_heal_card(self, game_engine, player, card):
        """使用桃恢复体力"""
        # 使用桃牌
        if hasattr(card, 'use'):
            card.use(game_engine, player, None)  # 桃不需要目标
            # 确保从手牌移除
            if card in player.hand:
                player.hand.remove(card)
                if hasattr(game_engine, 'discard_pile'):
                    game_engine.discard_pile.append(card)
        else:
            # 如果没有use方法，进行简化处理
            player.health = min(player.health + 1, player.max_health)
            if card in player.hand:
                player.hand.remove(card)
                if hasattr(game_engine, 'discard_pile'):
                    game_engine.discard_pile.append(card)
        
        print(f"{player.name} 使用了桃，恢复了1点体力！")
    
    def _use_wine_card(self, game_engine, player, card):
        """使用酒"""
        # 简单处理
        print(f"{player.name} 使用了酒！")
        if card in player.hand:
            player.hand.remove(card)
            if hasattr(game_engine, 'discard_pile'):
                game_engine.discard_pile.append(card)
    
    def _equip_card(self, game_engine, player, card):
        """装备卡牌"""
        # 检查是否已装备同类型的卡牌
        equip_type = card.subtype
        existing_equip = None
        
        # 查找并移除同类型的装备
        for equip in player.equipment_area[:]:
            if equip.subtype == equip_type:
                existing_equip = equip
                player.equipment_area.remove(equip)
                # 添加到弃牌堆
                if hasattr(game_engine, 'discard_pile'):
                    game_engine.discard_pile.append(equip)
                break
        
        # 装备新卡牌
        player.equipment_area.append(card)
        
        # 从手牌移除
        if card in player.hand:
            player.hand.remove(card)
        
        print(f"{player.name} 装备了 {card.name}！")
        if existing_equip:
            print(f"{player.name} 替换了装备：{existing_equip.name} -> {card.name}")
    
    def _use_trick_card(self, game_engine, player, card):
        """使用锦囊牌"""
        # 简化处理，自动使用
        print(f"{player.name} 使用了锦囊牌: {card.name}！")
        if hasattr(card, 'use'):
            card.use(game_engine, player, None)  # 简化处理，不传目标
            # 确保从手牌移除
            if card in player.hand:
                player.hand.remove(card)
                if hasattr(game_engine, 'discard_pile'):
                    game_engine.discard_pile.append(card)
        else:
            # 从手牌移除
            if card in player.hand:
                player.hand.remove(card)
                if hasattr(game_engine, 'discard_pile'):
                    game_engine.discard_pile.append(card)
    
    def _is_in_attack_range(self, player, target):
        """检查攻击距离"""
        # 基础距离为1
        attack_range = 1
        
        # 考虑武器加成
        if hasattr(player, 'weapon') and player.weapon and hasattr(player.weapon, 'range'):
            attack_range = player.weapon.range
        
        # 考虑坐骑加成
        if hasattr(player, 'attack_mount') and player.attack_mount and hasattr(player.attack_mount, 'attack_bonus'):
            attack_range += player.attack_mount.attack_bonus
        
        # 目标的防御坐骑增加距离
        if hasattr(target, 'defend_mount') and target.defend_mount and hasattr(target.defend_mount, 'defense_bonus'):
            attack_range -= target.defend_mount.defense_bonus
        
        # 简化版的距离检查，实际游戏中应该基于座位顺序计算距离
        # 这里假设所有角色都在攻击范围内
        return attack_range >= 1
    
    def _render_game_screen(self, game_engine: GameEngine):
        """渲染游戏界面"""
        # 绘制玩家信息
        self._render_players(game_engine.get_characters(), game_engine.get_current_player())
        
        # 绘制当前玩家的手牌
        self._render_hand(game_engine.get_current_player())
        
        # 绘制游戏信息
        self._render_game_info(game_engine)
    
    def _render_players(self, players: List[Character], current_player: Optional[Character]):
        """渲染玩家信息"""
        if not players:
            return
            
        # 顶部玩家
        top_players = [p for i, p in enumerate(players) if i > 0]  # 除了当前玩家外的所有玩家
        player_width, player_height = 120, 80
        
        # 计算顶部玩家的起始位置，使其居中
        total_width = len(top_players) * (player_width + 20)
        start_x = (self.width - total_width) // 2
        
        for i, player in enumerate(top_players):
            x = start_x + i * (player_width + 20)
            y = 50
            self._render_other_player(player, x, y, current_player == player)
    
    def _render_bottom_player(self, player: Character, is_current: bool):
        """渲染底部玩家（当前玩家）"""
        if not player:
            return
            
        # 玩家信息框
        rect = pygame.Rect(50, self.height - 150, self.width - 100, 100)
        color = (255, 215, 0) if is_current else (100, 100, 100)
        pygame.draw.rect(self.window, color, rect)
        pygame.draw.rect(self.window, (0, 0, 0), rect, 2)
        
        # 显示玩家信息
        # 获取角色对应的颜色
        role_color = self._get_role_color(player.role)
        info = f"{player.name} ({player.role})"
        health_info = f"体力: {player.health}/{player.max_health}"
        
        text = self.font.render(info, True, role_color)
        health_text = self.font.render(health_info, True, (255, 0, 0) if player.health <= player.max_health // 2 else (0, 0, 0))
        
        self.window.blit(text, (60, self.height - 140))
        self.window.blit(health_text, (60, self.height - 110))
        
        # 显示阵营
        faction_color = self._get_faction_color(player.faction)
        faction_text = self.small_font.render(player.faction, True, faction_color)
        self.window.blit(faction_text, (self.width - 70, self.height - 140))
        
        # 渲染玩家的装备区
        self._render_equipment_area(player)    
        
    def _render_equipment_area(self, player: Character):
        """渲染玩家的装备区"""
        if not player or not player.equipment_area:
            return
        
        # 装备牌大小（缩小版）
        card_width, card_height = 60, 80
        start_x = (self.width - (card_width * len(player.equipment_area) + 10 * (len(player.equipment_area) - 1))) // 2
        y_pos = self.height - 230  # 在玩家信息框上方显示装备
        
        for i, equip in enumerate(player.equipment_area):
            # 计算装备位置
            equip_x = start_x + i * (card_width + 10)
            
            # 绘制装备卡牌
            equip_rect = pygame.Rect(equip_x, y_pos, card_width, card_height)
            color = self._get_card_color(equip)
            pygame.draw.rect(self.window, color, equip_rect)
            pygame.draw.rect(self.window, (0, 0, 0), equip_rect, 2)
            
            # 显示装备名称
            equip_text = self.small_font.render(equip.name, True, (0, 0, 0))
            text_rect = equip_text.get_rect(center=(equip_x + card_width // 2, y_pos + card_height // 2))
            self.window.blit(equip_text, text_rect)
    
    def _get_role_color(self, role):
        """根据角色获取颜色"""
        color_map = {
            ROLE_LORD: (255, 0, 0),       # 主公 - 红色
            ROLE_LOYAL: (0, 128, 0),      # 忠臣 - 绿色
            ROLE_REBEL: (0, 0, 128),      # 反贼 - 蓝色
            ROLE_TRAITOR: (128, 0, 128)   # 内奸 - 紫色
        }
        return color_map.get(role, (0, 0, 0))
    
    def _get_faction_color(self, faction):
        """根据阵营获取颜色"""
        color_map = {
            "魏": (200, 200, 200),    # 魏国 - 灰色
            "蜀": (255, 50, 50),      # 蜀国 - 红色
            "吴": (50, 100, 200),     # 吴国 - 蓝色
            "群": (150, 75, 0)        # 群雄 - 棕色
        }
        return color_map.get(faction, (255, 255, 255))
    
    def _render_other_player(self, player: Character, x: int, y: int, is_current: bool):
        """渲染其他玩家"""
        if not player:
            return
            
        # 玩家信息框
        rect = pygame.Rect(x, y, 120, 80)
        color = (255, 215, 0) if is_current else (100, 100, 100)
        pygame.draw.rect(self.window, color, rect)
        pygame.draw.rect(self.window, (0, 0, 0), rect, 2)
        
        # 显示玩家信息
        name_text = self.small_font.render(player.name, True, (0, 0, 0))
        health_text = self.small_font.render(f"{player.health}/{player.max_health}", True, 
                                           (255, 0, 0) if player.health <= player.max_health // 2 else (0, 0, 0))
        
        # 确保文本在框内居中
        name_rect = name_text.get_rect(center=(x + 60, y + 25))
        health_rect = health_text.get_rect(center=(x + 60, y + 55))
        
        self.window.blit(name_text, name_rect)
        self.window.blit(health_text, health_rect)
        
        # 显示角色标识
        role_color = self._get_role_color(player.role)
        pygame.draw.circle(self.window, role_color, (x + 105, y + 15), 8)
    
    def _render_hand(self, player: Optional[Character]):
        """渲染玩家手牌"""
        if not player or not player.is_human or not player.hand:
            return
        
        card_width, card_height = 80, 120
        start_x = (self.width - (card_width * len(player.hand) + 10 * (len(player.hand) - 1))) // 2
        
        for i, card in enumerate(player.hand):
            # 计算卡牌位置
            card_x = start_x + i * (card_width + 10)
            card_y = self.height - 220
            
            # 如果是选中的卡牌，稍微向上偏移
            if card == self.selected_card:
                card_y -= 10
            
            # 绘制卡牌
            card_rect = pygame.Rect(card_x, card_y, card_width, card_height)
            color = self._get_card_color(card)
            pygame.draw.rect(self.window, color, card_rect)
            pygame.draw.rect(self.window, (0, 0, 0), card_rect, 2)
            
            # 显示卡牌名称
            card_text = self.small_font.render(card.name, True, (0, 0, 0))
            text_rect = card_text.get_rect(center=(card_x + card_width // 2, card_y + card_height // 2))
            self.window.blit(card_text, text_rect)
            
            # 显示花色和点数
            if hasattr(card, 'suit') and hasattr(card, 'number'):
                suit_text = self.small_font.render(card.suit, True, (0, 0, 0))
                number_text = self.small_font.render(str(card.number), True, (0, 0, 0))
                self.window.blit(suit_text, (card_x + 5, card_y + 5))
                self.window.blit(number_text, (card_x + 5, card_y + 25))
    
    def _get_card_color(self, card):
        """根据卡牌类型获取颜色"""
        if card.card_type == "basic":
            # 基础牌颜色
            if card.name == "杀":
                return (220, 50, 50)  # 杀 - 红色
            elif card.name == "闪":
                return (100, 150, 255)  # 闪 - 蓝色
            elif card.name == "桃":
                return (255, 150, 150)  # 桃 - 粉色
            elif card.name == "酒":
                return (180, 120, 80)  # 酒 - 棕色
        elif card.card_type == "equipment":
            # 装备牌颜色
            if hasattr(card, 'subtype'):
                if card.subtype == "weapon":
                    return (200, 200, 200)  # 武器 - 银色
                elif card.subtype == "armor":
                    return (255, 215, 0)  # 防具 - 金色
                elif "mount" in card.subtype:
                    return (139, 69, 19)  # 坐骑 - 棕色
        elif card.card_type == "trick":
            # 锦囊牌颜色
            return (200, 100, 200)  # 锦囊 - 紫色
        
        # 默认颜色
        return (255, 255, 255)
    
    def _render_game_info(self, game_engine: GameEngine):
        """渲染游戏信息"""
        # 显示当前回合和阶段
        phase_text = self.font.render(f"当前阶段: {game_engine.get_current_phase()}", True, (255, 255, 255))
        self.window.blit(phase_text, (50, self.height - 50))
        
        # 显示当前玩家
        current_player = game_engine.get_current_player()
        if current_player:
            player_text = self.font.render(f"当前回合: {current_player.name}", True, (255, 255, 255))
            self.window.blit(player_text, (self.width - 250, self.height - 50))
        
        # 绘制底部玩家
        self._render_bottom_player(current_player, True)
        
        # 显示操作提示（只有在玩家回合的出牌阶段）
        if current_player and current_player.is_human and game_engine.current_phase == "出牌阶段":
            hint_text = self.small_font.render("点击卡牌使用，按空格键结束回合", True, (255, 255, 255))
            self.window.blit(hint_text, (self.width//2 - hint_text.get_width()//2, 20))
    
    def _get_clicked_card(self, mouse_pos: tuple, game_engine: GameEngine) -> Optional[Card]:
        """获取被点击的卡牌"""
        current_player = game_engine.get_current_player()
        if not current_player or not current_player.is_human:
            return None
        
        card_width, card_height = 80, 120
        start_x = (self.width - (card_width * len(current_player.hand) + 10 * (len(current_player.hand) - 1))) // 2
        
        for i, card in enumerate(current_player.hand):
            # 计算卡牌位置（考虑选中状态）
            card_y = self.height - 220
            if card == self.selected_card:
                card_y -= 10
            
            card_rect = pygame.Rect(start_x + i * (card_width + 10), card_y, card_width, card_height)
            if card_rect.collidepoint(mouse_pos):
                return card
        
        return None
    
    def _render_game_over_screen(self, game_engine: GameEngine):
        """渲染游戏结束界面"""
        # 绘制半透明遮罩
        overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 150))  # 半透明黑色
        self.window.blit(overlay, (0, 0))
        
        # 显示游戏结束信息
        title = self.large_font.render("游戏结束", True, (255, 215, 0))
        title_rect = title.get_rect(center=(self.width//2, self.height//2 - 80))
        self.window.blit(title, title_rect)
        
        winner_role = game_engine.get_winner_role()
        if winner_role:
            winner_text = self.font.render(f"获胜方：{winner_role}", True, (255, 255, 255))
            winner_rect = winner_text.get_rect(center=(self.width//2, self.height//2 - 30))
            self.window.blit(winner_text, winner_rect)
        
        # 显示返回按钮
        self.back_button.show()
    
    def get_player_count(self) -> int:
        """获取玩家数量"""
        return self.player_count